package com.junxi.microservices.bookstore.product.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    /**
     * 配置安全过滤链
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/public/**", "/test/**").permitAll()
                        // client_credentials模式下，权限前缀是SCOPE_
                        .requestMatchers("/products/**").hasAnyAuthority("SCOPE_product.read", "SCOPE_product.write")
                        .requestMatchers("/admin/**").hasAnyAuthority("SCOPE_product.write", "ROLE_ADMIN")
                        .anyRequest().authenticated()
                )
                // 关键：显式配置未认证请求的处理逻辑，强制跳转到OAuth2授权页面
//                .exceptionHandling(ex -> ex
//                        .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login/oauth2/code/auth-service"))
//                )
                .oauth2Login(oauth2 -> oauth2
                        .defaultSuccessUrl("/products", false)
                        .failureUrl("/public/login-fail")     // 登录失败跳转的页面
                )
                .oauth2ResourceServer(oauth2 -> oauth2
                        .jwt(jwt -> jwt
                                .jwtAuthenticationConverter(jwtAuthenticationConverter())
                        )
                );// client_credentials模式不需要oauth2Login配置，因为没有用户交互，直接获取token，然后使用token访问资源

        http.formLogin(AbstractHttpConfigurer::disable); // 禁用表单登录

        return http.build();
    }

    /**
     * JWT认证转换器，用于将JWT中的声明转换为Spring Security的权限
     */
    @Bean
    public JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
//        grantedAuthoritiesConverter.setAuthoritiesClaimName("roles");
//        grantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
        // 客户端凭证模式下，权限在scope中，默认前缀是SCOPE_
        grantedAuthoritiesConverter.setAuthorityPrefix("SCOPE_");
        grantedAuthoritiesConverter.setAuthoritiesClaimName("scope");

        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
        return jwtAuthenticationConverter;
    }

//    /**
//     * 配置OAuth2授权客户端管理器
//     */
//    @Bean
//    public OAuth2AuthorizedClientManager authorizedClientManager(
//            ClientRegistrationRepository clientRegistrationRepository,
//            OAuth2AuthorizedClientRepository authorizedClientRepository) {
//
//        // 配置client_credentials授权提供者
//        OAuth2AuthorizedClientProvider authorizedClientProvider =
//                OAuth2AuthorizedClientProviderBuilder.builder()
//                        .clientCredentials()
//                        .authorizationCode()
//                        .refreshToken()
//                        .build();
//
//        // 创建默认授权客户端管理器
//        DefaultOAuth2AuthorizedClientManager authorizedClientManager =
//                new DefaultOAuth2AuthorizedClientManager(
//                        clientRegistrationRepository, authorizedClientRepository);
//        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
//
//        return authorizedClientManager;
//    }
}
